#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import sys

from common.common import exter_attack
from common.exception.common_exception import ErrCodeException
from generaldb.saphana.backup.saphana_backup_service import BackupService
from common.const import SysData
from generaldb.saphana.comm.common_util import log
from common.parse_parafile import ParamFileUtil
from generaldb.saphana.comm.saphana_const import SaphanaServiceConst
from generaldb.saphana.resources.saphana_resource_service import SapHanaResourceService
from generaldb.saphana.restore.saphana_restore_service import SaphanaRestoreService


class SaphanaApi:

    @staticmethod
    @exter_attack
    def check_application(pid, job_id, sub_job_id):
        resource_service = SapHanaResourceService(SaphanaServiceConst.CHECK_APPLICATION, pid,
                                                  ParamFileUtil.parse_param_file(pid))
        resource_service.check_application(resource_service.get_manager())

    @staticmethod
    @exter_attack
    def list_application_resource(pid, job_id, sub_job_id):
        resource_service = SapHanaResourceService(SaphanaServiceConst.LIST_APPLICATION_RESOURCE, pid,
                                                  ParamFileUtil.parse_param_file(pid))
        resource_service.list_application_resource(resource_service.get_manager())

    @staticmethod
    @exter_attack
    def check_backup_job_type(pid, job_id, sub_job_id):
        backup_service = BackupService(pid, job_id, "")
        if not backup_service.check_backup_type():
            log.error(f"Check backup type failed. job id: {job_id}")

    @staticmethod
    @exter_attack
    def query_job_permission(pid, job_id, sub_job_id):
        if not BackupService.query_job_permission(pid, job_id, ""):
            log.error(f"Query job permission failed. job id: {job_id}")

    @staticmethod
    @exter_attack
    def allow_backup_in_local_node(pid, job_id, sub_job_id):
        backup_service = BackupService(pid, job_id, "")
        if not backup_service.allow_backup_in_local_node():
            log.error(f"Can not run backup in local node. job id: {job_id}")

    @staticmethod
    @exter_attack
    def allow_backup_sub_job_in_local_node(pid, job_id, sub_job_id):
        pass

    @staticmethod
    @exter_attack
    def backup_prerequisite(pid, job_id, sub_job_id):
        backup_service = BackupService(pid, job_id, "")
        backup_service.exec_prerequisite_task()

    @staticmethod
    @exter_attack
    def backup_gen_sub_job(pid, job_id, sub_job_id):
        backup_service = BackupService(pid, job_id, "")
        backup_service.generate_subjob()

    @staticmethod
    @exter_attack
    def backup(pid, job_id, sub_job_id):
        backup_service = BackupService(pid, job_id, sub_job_id)
        if not backup_service.exec_subjob():
            return

    @staticmethod
    @exter_attack
    def backup_post_job(pid, job_id, sub_job_id):
        backup_service = BackupService(pid, job_id, sub_job_id)
        backup_service.exec_post_job()

    @staticmethod
    @exter_attack
    def backup_post_job_progress(pid, job_id, sub_job_id):
        pass

    @staticmethod
    @exter_attack
    def abort_job(pid, job_id, sub_job_id):
        backup_service = BackupService(pid, job_id, sub_job_id)
        backup_service.abort_backup()

    @staticmethod
    @exter_attack
    def query_backup_copy(pid, job_id, sub_job_id):
        pass

    @staticmethod
    @exter_attack
    def allow_restore_in_local_node(pid, job_id, sub_job_id):
        restore_service = SaphanaRestoreService(pid, job_id, sub_job_id)
        if not restore_service.allow_restore_in_local_node():
            log.error(f"Can not run restore in local node. job id: {job_id}")

    @staticmethod
    @exter_attack
    def restore_prerequisite(pid, job_id, sub_job_id):
        restore_service = SaphanaRestoreService(pid, job_id, sub_job_id)
        if not restore_service.restore_prerequisite():
            log.error(f"Can not run restore prerequisite. job id: {job_id}")

    @staticmethod
    @exter_attack
    def restore(pid, job_id, sub_job_id):
        restore_service = SaphanaRestoreService(pid, job_id, sub_job_id)
        if not restore_service.restore():
            log.error(f"Can not run restore. job id: {job_id}")

    @staticmethod
    @exter_attack
    def restore_post_job(pid, job_id, sub_job_id):
        restore_service = SaphanaRestoreService(pid, job_id, sub_job_id)
        if not restore_service.restore_post_job():
            log.error(f"Can not run restore post jop. job id: {job_id}")

    @staticmethod
    @exter_attack
    def restore_gen_sub_job(pid, job_id, sub_job_id):
        restore_service = SaphanaRestoreService(pid, job_id, sub_job_id)
        if not restore_service.restore_gen_sub_job():
            log.error(f"Can not run restore gen sub jop. job id: {job_id}")


func_dict = {
    SaphanaServiceConst.CHECK_APPLICATION: SaphanaApi.check_application,
    SaphanaServiceConst.LIST_APPLICATION_RESOURCE: SaphanaApi.list_application_resource,
    'AllowBackupInLocalNode': SaphanaApi.allow_backup_in_local_node,
    'AllowBackupSubJobInLocalNode': SaphanaApi.allow_backup_sub_job_in_local_node,
    'CheckBackupJobType': SaphanaApi.check_backup_job_type,
    'QueryJobPermission': SaphanaApi.query_job_permission,
    'BackupPrerequisite': SaphanaApi.backup_prerequisite,
    'BackupGenSubJob': SaphanaApi.backup_gen_sub_job,
    'Backup': SaphanaApi.backup,
    'BackupPostJob': SaphanaApi.backup_post_job,
    'BackupPostJobProgress': SaphanaApi.backup_post_job_progress,
    'QueryBackupCopy': SaphanaApi.query_backup_copy,
    'AbortJob': SaphanaApi.abort_job,
    'PauseJob': SaphanaApi.abort_job,
    'AllowRestoreInLocalNode': SaphanaApi.allow_restore_in_local_node,
    'RestorePrerequisite': SaphanaApi.restore_prerequisite,
    'RestoreGenSubJob': SaphanaApi.restore_gen_sub_job,
    'Restore': SaphanaApi.restore,
    'RestorePostJob': SaphanaApi.restore_post_job
}


def saphana_main(hana_args):
    """
    功能描述：主任务执行
    参数：
    @fun_type：argv[0] 方法类型
    @pid：argv[1] 请求ID
    @job_id：argv[2] 主任务任务ID
    @sub_job_id: argv[3] 子任务ID
    例：python3 api.py fun_type pid job_id sub_job_id
    """
    def is_valid_uuid(uuid_string):
        import re
        return bool(re.search(r"[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}", uuid_string))

    fun_type = hana_args[0]
    pid = hana_args[1]
    job_id = ''
    sub_job_id = ''
    if len(hana_args) > 2:
        job_id = hana_args[2]
        if not is_valid_uuid(job_id):
            log.error(f"Job({job_id}) id is error")
            return 
    if len(hana_args) > 3:
        sub_job_id = hana_args[3]
        if not is_valid_uuid(sub_job_id):
            log.error(f"Sub job({sub_job_id}) id is error")
            return
    log.info(f'######## function: {fun_type} start, pid: {pid}, job_id: {job_id}, sub_job_id: {sub_job_id}')
    try:
        func_dict[fun_type](pid, job_id, sub_job_id)
    except KeyError as err:
        log.error(f'######## function: {fun_type} not exist {err}', exc_info=1)
    except ErrCodeException as errcode_str:
        log.error(f'######## function: {fun_type} exception {errcode_str}', exc_info=1)
    except Exception as exception_str:
        log.error(f'######## function: {fun_type} exception {exception_str}', exc_info=1)
    log.info(f'######## function: {fun_type} end, pid: {pid}')


if __name__ == '__main__':
    for line in sys.stdin:
        SysData.SYS_STDIN = line
        break
    args = sys.argv[1:]
    saphana_main(args)
